#include "bsp_config.h"

static KEY_DOWN_TIME_FLAG_Typedef Key_Time_Flag[NUM_OF_KEY] = {KEY_ALL, KEY_ALL, KEY_ALL}; //用来区分长按的时间
static KEY_STATE_Typedef KeyStateEnum = KEY_RELEASE;									   //用来记录当前按键状态

//定义按键当前状态数组变量
static uint8_t key_state[NUM_OF_KEY] = {0, 0, 0};
//记录当前按键按下的时间(单位ms)
static uint32_t key_down_time[NUM_OF_KEY] = {0, 0, 0};

// SET:KEY3 0    SHIFT:KEY2 1    UP:KEY1 2
// SET_LONG_KEY 3     SHIFT_LONG_KEY 4    INC_LONG_KEY 5

/**
 *  @brief 获取当前按键状态   写的有些巧妙
 *  @param 无
 *  @brief 当前按键状态
 */
KEY_STATE_Typedef GetCurrentKeyState(void)
{
	KEY_STATE_Typedef KeyStateBuff;

	KeyStateBuff = KeyStateEnum;
	KeyStateEnum = KEY_RELEASE; //吃完就没有了

	return KeyStateBuff;
}

/**
 *  @brief 按键动作函数,根据输入的键码,执行相应的动作
 *  @param keycode :键码
 *  @brief 无
 */
static void KeyAction(uint8_t keycode)
{
	switch (keycode)
	{
		/********************************这里是短按************************************/
	case SET_KEY:
		printf("SET_KEY");
		KeyStateEnum = SET_KET_PRESS;
		break;
	case SHIFT_KEY:
		printf("SHIFT_KEY");
		KeyStateEnum = SHIFT_KEY_PRESS;
		break;
	case INC_KEY:
		printf("INC_KEY");
		KeyStateEnum = INC_KEY_PRESS;
		break;
		/**********************************这里是2s长按***********************************/
	case SET_LONG_2S_KEY:
		printf("SET_LONG_2S_KEY");
		KeyStateEnum = SET_KEY_LONG_PRESS_2S;
		break;
	case SHIFT_LONG_2S_KEY:
		printf("SHIFT_LONG_2S_KEY");
		KeyStateEnum = SHIFT_KEY_LONG_PRESS_2S;
		break;
	case INC_LONG_2S_KEY:
		printf("INC_LONG_2S_KEY");
		KeyStateEnum = INC_KEY_LONG_PRESS_2S;
		break;
		/**********************************这里是4s长按***********************************/
	case SET_LONG_4S_KEY:
		printf("SET_LONG_4S_KEY");
		KeyStateEnum = SET_KEY_LONG_PRESS_4S;
		break;
	case SHIFT_LONG_4S_KEY:
		printf("SHIFT_LONG_4S_KEY");
		KeyStateEnum = SHIFT_KEY_LONG_PRESS_4S;
		break;
	case INC_LONG_4S_KEY:
		printf("INC_LONG_4S_KEY");
		KeyStateEnum = INC_KEY_LONG_PRESS_4S;
		break;
	default:
		break;
	}
}

/**
 *	@brief  按键驱动函数,需要每隔一定时间进行一次调用
 *	@param	无
 *	@return	无
 */
static void Key_Driver(void)
{
	static uint8_t key_state_buff[NUM_OF_KEY] = {0, 0, 0}; //默认初始电平是低电平
	uint8_t i;

	/**
	 *  长按蜂鸣器响三下(有2s长按  4s长按)   短按蜂鸣器响一下
	 */

	for (i = 0; i < NUM_OF_KEY; ++i)
	{							  //这里是长按
		if (key_down_time[i] > 0) //很关键
		{						  //表示当前按键是被按下去的  但得区分是4s长按  还是2s长按
			if ((key_down_time[i] > KEY_DOWN_TIME_2S_THRESHOLD) && (Key_Time_Flag[i] == KEY_ALL))
			{ //按键按下时间超过2S阈值时间
				Key_Time_Flag[i] = KEY_DOWN_2S_FLAG;
				beep_queue_enum = BEEP_THREE;
				pBEEP_QUEUE_ENUM = &beep_queue_enum;
				xQueueSend(beep_QueueHandler, (void *)&pBEEP_QUEUE_ENUM, portMAX_DELAY);
			}
			else if ((key_down_time[i] > KEY_DOWN_TIME_4S_THRESHOLD) && (Key_Time_Flag[i] == KEY_DOWN_2S_FLAG))
			{
				Key_Time_Flag[i] = KEY_DOWN_4S_FLAG;
				beep_queue_enum = BEEP_THREE;
				pBEEP_QUEUE_ENUM = &beep_queue_enum;
				xQueueSend(beep_QueueHandler, (void *)&pBEEP_QUEUE_ENUM, portMAX_DELAY);
			}
		}
	}

	for (i = 0; i < NUM_OF_KEY; ++i)
	{										   //这里是短按
		if (key_state_buff[i] != key_state[i]) //按键被按下或弹起(只执行变化时的值)
		{
			//备份按键的状态
			key_state_buff[i] = key_state[i];
			if (key_state[i] == 0) //按键弹起 按键弹起有短按弹起 2s长按弹起  4s长按弹起
			{
				if (Key_Time_Flag[i] != KEY_ALL)
				{ //表示长按
					if (Key_Time_Flag[i] == KEY_DOWN_2S_FLAG)
					{
						KeyAction(i * 3 + 1); // 2秒按下
					}
					else if (Key_Time_Flag[i] == KEY_DOWN_4S_FLAG)
					{
						KeyAction(i * 3 + 2); // 4秒按下
					}
					Key_Time_Flag[i] = KEY_ALL; //还原
				}
				else
				{ //表示短按
					beep_queue_enum = BEEP_ONCE;
					pBEEP_QUEUE_ENUM = &beep_queue_enum;
					xQueueSend(beep_QueueHandler, (void *)&pBEEP_QUEUE_ENUM, portMAX_DELAY);
					KeyAction(i * 3 + 0); //调用KeyAction函数
				}
			}
		}
	}
}

// SET:KEY3 0    SHIFT:KEY2 1    UP:KEY1 2

/**
 * @brief  按键扫描函数(通过软件滤波来更新当前的按键状态  20ms调用一次)
 * @param  无
 * @retval 无
 */
static void KEY_Scan(void)
{
	uint8_t key_result;

	key_result = TM1638_ReadKey();

	if ((key_result & 0x01) == 0x01) //表明K3(SET)按了下去
	{								 //按下去了    每8ms调用一次
		key_state[SET] = 1;
		key_down_time[SET] += 8;
	}
	else if ((key_result & 0x01) == 0x00) //表明K3(SET)没有被
	{									  //没有被按下
		key_state[SET] = 0;
		key_down_time[SET] = 0;
	}

	if ((key_result & 0x02) == 0x02) //表明K2(SHIFT)按了下去
	{								 //按下去了    每8ms调用一次
		key_state[SHIFT] = 1;
		key_down_time[SHIFT] += 8;
	}
	else if ((key_result & 0x02) == 0x00) //表明K2(SHIFT)没有被
	{									  //没有被按下
		key_state[SHIFT] = 0;
		key_down_time[SHIFT] = 0;
	}

	if ((key_result & 0x04) == 0x04) //表明K1(UP)按了下去
	{								 //按下去了    每8ms调用一次
		key_state[UP] = 1;
		key_down_time[UP] += 8;
	}
	else if ((key_result & 0x04) == 0x00) //表明K1(UP)没有被
	{									  //没有被按下
		key_state[UP] = 0;
		key_down_time[UP] = 0;
	}
}

/**
 *  @brief 按键驱动线程,需要每隔一定时间进行一次调用  20ms  其实还可以更长时间
 *  @param param :void 类型的指针
 *  @brief 无
 */
void Key_Driver_Task(void *param)
{
	while (1)
	{
		xSemaphoreTake(tm1638_mutex, portMAX_DELAY);
		KEY_Scan();
		Key_Driver();
		xSemaphoreGive(tm1638_mutex);
		Pump_Cnt_Scan(); //这里就是和泵操作相关的
		Pump_Cnt_Driver();
		vTaskDelay(8 / portTICK_PERIOD_MS); //每过8ms扫描一次按键
	}
}
